package top.bingoz.wanandroid.common.upgrade

import android.app.DownloadManager
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import android.support.v4.content.FileProvider
import android.util.LongSparseArray
import top.bingoz.wanandroid.BuildConfig
import top.bingoz.wanandroid.R
import java.io.File


/**
 *  CreateDate: 2018/6/11
 *  Desc:  系统下载管理
 */
class DownloadApkManager {


    private var mDownLoadManager: DownloadManager? = null
    var mApkPaths: LongSparseArray<String> = LongSparseArray()
    var downloadID: Long = DownloadState.DOWN_LOAD_INIT_ID

    fun getDownloadManager(context: Context): DownloadManager {
        if (mDownLoadManager == null) {
            synchronized(DownloadApkManager::class) {
                if (mDownLoadManager == null) {
                    mDownLoadManager = context.applicationContext.getSystemService(Context.DOWNLOAD_SERVICE)
                            as DownloadManager
                }
            }
        }
        return mDownLoadManager!!
    }

    /**
     *  调用系统 下载方法 下载 apk
     *  @param context 上下文
     *  @param url  下载链接
     *  @param apkName 应用名称
     *  @param apkMd5 应用 MD5 值
     *  @param apkDesc  apk 描述信息
     *  @return Long 下载状态
     */
    fun startDownload(context: Context, url: String, apkDesc: CharSequence?): Long {
        return startDownload(context, url, context.getString(R.string.app_name), null, apkDesc)
    }

    /**
     *  调用系统 下载方法 下载 apk
     *  @param context 上下文
     *  @param url  下载链接
     *  @param apkName 应用名称
     *  @param apkMd5 应用 MD5 值
     *  @param apkDesc  apk 描述信息
     *  @return Long 下载状态
     */
    fun startDownload(context: Context, url: String, apkName: String,
                      apkMd5: String?, apkDesc: CharSequence?): Long {
        val downLoadManagerIsEnabled = DownloadUtils.isDownLoadManagerEnabled(context)
        if (!downLoadManagerIsEnabled) {
            val packageName = "com.android.providers.downloads"
            try {
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                intent.setData(Uri.parse("package:$packageName"))
                context.startActivity(intent)
            } catch (e: ActivityNotFoundException) {
                val intent = Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
                context.startActivity(intent)
            }
            return DownloadState.DOWN_LOAD_MANAGER_UNABLE_USE
        }
        if (downloadID != DownloadState.DOWN_LOAD_INIT_ID) return DownloadState.DOWN_LOAD_INIT_ID
        val clearApk = isClearApk(context, apkName, apkMd5)
        if (!clearApk) return DownloadState.DOWN_LOAD_APK_HAS_EXIST
        val fileDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
        // 检测当前SD 卡状态是否读写及文件路径是否存在可用，不可用时中断下载操作
        if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED || fileDir == null)
            return DownloadState.EXTERNAL_STORAGE_NOT_EXIST
        val req = DownloadManager.Request(Uri.parse(url))
        req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
        //点击正在下载的Notification进入下载详情界面，如果设为true则可以看到下载任务的进度，如果设为false，则看不到我们下载的任务
        req.setVisibleInDownloadsUi(true)
        //设置文件的保存的位置/自定义文件路径
        val file = File(fileDir, apkName)

        val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.fileProvider", file)
        req.setDestinationUri(uri)
        //req.setDestinationUri(Uri.fromFile(file))
        // 此方法表示在下载过程中通知栏会一直显示该下载，在下载完成后仍然会显示，
        // 直到用户点击该通知或者消除该通知。还有其他参数可供选择
        req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        // 通过setAllowedNetworkTypes方法可以设置允许在何种网络下下载，
        // 也可以使用setAllowedOverRoaming方法，它更加灵活移动网络是否允许下载
        req.setAllowedOverRoaming(true)
        // 设置一些基本显示信息
        req.setTitle(apkName)
        req.setDescription(apkDesc)
        req.setMimeType("application/vnd.android.package-archive")
        //加入下载队列
        downloadID = getDownloadManager(context).enqueue(req)
        mApkPaths.put(downloadID, file.absolutePath)
        return downloadID

    }

    /**
     * 如果之前下载过已经存在apk,删除之前的apk
     *
     * @param apkName apk名字
     * @param apkMd5     apk md5 信息
     * @return true 继续执行下载任务， false 中断下载任务
     */
    private fun isClearApk(context: Context, apkName: String, apkMd5: String?): Boolean {
        apkMd5 ?: return true
        val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), apkName)
        if (file.exists() && DownloadUtils.getFileMd5(file) != null) {
            if ("" != apkMd5 && apkMd5 == DownloadUtils.getFileMd5(file)) {
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {// Android N 及以上安装方法
                    DownloadUtils.installApk4AndroidN(context, file)
                } else {// Android N 以下安装apk
                    val data = Uri.parse("file://$file")
                    DownloadUtils.installApk4AndroidM(context, data)
                }
                return false
            }
            file.delete()
        }
        return true
    }

    companion object {
        var mInstance: DownloadApkManager? = null

        fun getInstance(): DownloadApkManager {
            if (mInstance == null) {
                synchronized(DownloadApkManager::class) {
                    if (mInstance == null) {
                        mInstance = DownloadApkManager()
                    }
                }
            }
            return mInstance!!
        }
    }
}